#ifndef DATAFRAME_H
#define DATAFRAME_H

#include <vector>
#include <string>
#include <unordered_map>
#include <memory>
#include <stdexcept>
#include "NDimsArray.h"

namespace EnvData {

/**
 * @brief 环境数据类型枚举
 */
enum class DataType {
    WIND_SPEED,        // 风速 (m/s)
    WIND_DIRECTION,    // 风向 (度)
    RAIN_RATE,         // 雨量率 (mm/h)
    TEMPERATURE,       // 温度 (°C)
    PRESSURE,          // 气压 (hPa)
    HUMIDITY          // 湿度 (%)
};

/**
 * @brief 时空坐标结构
 */
struct SpatioTemporalCoord {
    double latitude;   // 纬度
    double longitude;  // 经度
    double time;       // 时间戳 (Unix时间戳或相对时间)
    
    SpatioTemporalCoord(double lat = 0.0, double lon = 0.0, double t = 0.0)
        : latitude(lat), longitude(lon), time(t) {}
};

/**
 * @brief 环境数据存储和管理类
 * 
 * 使用NDimsArray作为底层存储，支持多维时空数据的高效访问
 */
class DataFrame {
private:
    std::unordered_map<DataType, std::shared_ptr<darr::DimsArray<double>>> data_arrays_;
    std::vector<std::string> dimension_names_;  // 维度名称 ["time", "latitude", "longitude"]
    std::vector<std::vector<double>> dimension_scales_;  // 各维度的刻度值
    
    bool is_initialized_;
    
public:
    /**
     * @brief 构造函数
     */
    DataFrame();
    
    /**
     * @brief 析构函数
     */
    ~DataFrame() = default;
    
    /**
     * @brief 初始化数据框架
     * @param time_points 时间点序列
     * @param latitudes 纬度序列
     * @param longitudes 经度序列
     */
    void initialize(const std::vector<double>& time_points,
                   const std::vector<double>& latitudes,
                   const std::vector<double>& longitudes);
    
    /**
     * @brief 添加环境数据
     * @param data_type 数据类型
     * @param data 数据数组，按时间、纬度、经度顺序排列
     */
    void addData(DataType data_type, const std::vector<double>& data);
    
    /**
     * @brief 设置三维嵌套数据
     * @param data_type 数据类型
     * @param nested_data 三维嵌套向量 [time][lat][lon]
     */
    void setNestedData(DataType data_type, 
                      const std::vector<std::vector<std::vector<double>>>& nested_data);
    
    /**
     * @brief 获取指定位置和时间的数据值
     * @param data_type 数据类型
     * @param coord 时空坐标
     * @return 数据值
     */
    double getValue(DataType data_type, const SpatioTemporalCoord& coord) const;
    
    /**
     * @brief 获取指定区域和时间范围的数据
     * @param data_type 数据类型
     * @param time_range 时间范围 [start_time, end_time]
     * @param lat_range 纬度范围 [min_lat, max_lat]
     * @param lon_range 经度范围 [min_lon, max_lon]
     * @return 区域数据的一维向量
     */
    std::vector<double> getRegionData(DataType data_type,
                                    const std::pair<double, double>& time_range,
                                    const std::pair<double, double>& lat_range,
                                    const std::pair<double, double>& lon_range) const;
    
    /**
     * @brief 获取时间序列数据
     * @param data_type 数据类型
     * @param latitude 固定纬度
     * @param longitude 固定经度
     * @return 时间序列数据
     */
    std::vector<double> getTimeSeries(DataType data_type, double latitude, double longitude) const;
    
    /**
     * @brief 获取空间分布数据（固定时间）
     * @param data_type 数据类型
     * @param time 固定时间
     * @return 空间分布数据的二维向量 [lat][lon]
     */
    std::vector<std::vector<double>> getSpatialDistribution(DataType data_type, double time) const;
    
    /**
     * @brief 检查数据类型是否存在
     * @param data_type 数据类型
     * @return 是否存在
     */
    bool hasDataType(DataType data_type) const;
    
    /**
     * @brief 获取维度大小
     * @return 维度大小向量 [time_size, lat_size, lon_size]
     */
    std::vector<size_t> getDimensionSizes() const;
    
    /**
     * @brief 获取时间范围
     * @return 时间范围 [min_time, max_time]
     */
    std::pair<double, double> getTimeRange() const;
    
    /**
     * @brief 获取纬度范围
     * @return 纬度范围 [min_lat, max_lat]
     */
    std::pair<double, double> getLatitudeRange() const;
    
    /**
     * @brief 获取经度范围
     * @return 经度范围 [min_lon, max_lon]
     */
    std::pair<double, double> getLongitudeRange() const;
    
    /**
     * @brief 清空所有数据
     */
    void clear();
    
    /**
     * @brief 检查是否已初始化
     * @return 是否已初始化
     */
    bool isInitialized() const { return is_initialized_; }
    
    /**
     * @brief 从文件加载数据（支持NetCDF格式等）
     * @param filename 文件名
     * @param data_type 数据类型
     * @return 是否加载成功
     */
    bool loadFromFile(const std::string& filename, DataType data_type);
    
    /**
     * @brief 导出数据到文件
     * @param filename 文件名
     * @param data_type 数据类型
     * @return 是否导出成功
     */
    bool saveToFile(const std::string& filename, DataType data_type) const;
    
private:
    /**
     * @brief 将数据类型转换为字符串
     * @param data_type 数据类型
     * @return 字符串表示
     */
    std::string dataTypeToString(DataType data_type) const;
    
    /**
     * @brief 验证坐标是否在有效范围内
     * @param coord 坐标
     * @return 是否有效
     */
    bool isValidCoordinate(const SpatioTemporalCoord& coord) const;
};

/**
 * @brief 环境数据管理器单例类
 * 
 * 提供全局环境数据访问接口
 */
class EnvironmentalDataManager {
private:
    static std::unique_ptr<EnvironmentalDataManager> instance_;
    std::unique_ptr<DataFrame> wind_data_;
    std::unique_ptr<DataFrame> rain_data_;
    std::unique_ptr<DataFrame> weather_data_;
    
    EnvironmentalDataManager();
    
public:
    /**
     * @brief 获取单例实例
     * @return 单例实例引用
     */
    static EnvironmentalDataManager& getInstance();
    
    /**
     * @brief 初始化风力数据
     * @param time_points 时间点
     * @param latitudes 纬度
     * @param longitudes 经度
     */
    void initializeWindData(const std::vector<double>& time_points,
                          const std::vector<double>& latitudes,
                          const std::vector<double>& longitudes);
    
    /**
     * @brief 初始化雨量数据
     * @param time_points 时间点
     * @param latitudes 纬度
     * @param longitudes 经度
     */
    void initializeRainData(const std::vector<double>& time_points,
                          const std::vector<double>& latitudes,
                          const std::vector<double>& longitudes);
    
    /**
     * @brief 获取风力数据框架
     * @return 风力数据框架引用
     */
    DataFrame& getWindData() { return *wind_data_; }
    
    /**
     * @brief 获取雨量数据框架
     * @return 雨量数据框架引用
     */
    DataFrame& getRainData() { return *rain_data_; }
    
    /**
     * @brief 获取天气数据框架
     * @return 天气数据框架引用
     */
    DataFrame& getWeatherData() { return *weather_data_; }
    
    /**
     * @brief 从配置文件加载所有环境数据
     * @param config_file 配置文件路径
     * @return 是否加载成功
     */
    bool loadAllData(const std::string& config_file);
    
    /**
     * @brief 清空所有数据
     */
    void clearAllData();
};

} // namespace EnvData

#endif // DATAFRAME_H 